/*
 * Open Source Physics software is free software as described near the bottom of this code file.
 *
 * For additional information and documentation on Open Source Physics please see:
 * <http://www.opensourcephysics.org/>
 */

package org.opensourcephysics.display;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;

public class InteractiveLabel extends MeasuredCircle implements Interactive {

   public static final int TOP_LEFT_LOCATION = 0;
   public static final int  CENTER_LOCATION = 1;
   public static final int TOP_CENTER_LOCATION = 2;
   public int connection_location = CENTER_LOCATION;
   boolean enabled = true;
   protected String text = null;
   protected Font font;
   protected String fontname = "TimesRoman"; // The logical name of the font to use
   protected int fontsize = 14;              // The font size
   protected int fontstyle = Font.PLAIN;     // The font style
   Box box = new Box();
   public InteractiveLabel() {
      super(0, 0);
      color=Color.YELLOW;
      pixRadius=1;
      font = new Font(fontname, fontstyle, fontsize);
   }

   public InteractiveLabel(String str) {
      this();
      text = GUIUtils.parseTeX(str);
   }

   public void setXY(double _x, double _y) {
      x = _x;
      y = _y;
   }

   public void setText(String _text) {
      text = GUIUtils.parseTeX(_text);
   }

   public void setText(String _text, double _x, double _y) {
      x = _x;
      y = _y;
      text = GUIUtils.parseTeX(_text);
   }

   public void resetBoxSize() {
      box.boxHeight = 0;
      box.boxWidth = 0;
   }

   /**
    * Sets the location of the connection point.
    * Location values are:TOP_LEFT_LOCATION, TOP_CENTER_LOCATION
    *
    * @param location int
    */
   public void setConnectionPoint(int location) {
      connection_location = location;
   }

   /**
    * Sets the label's offset in the x direction.
    * @param offset int
    */
   public void setOffsetX(int offset) {
      box.xoffset = offset;
   }

   /**
    * Gets the label's offset in the x direction.
    * @param offset int
    */
   public int getOffsetX() {
     return box.xoffset;
   }

   /**
    * Sets the label's offset in the y direction.
    * @param offset int
    */
   public void setOffsetY(int offset) {
      box.yoffset = offset;
   }

   /**
    * Gets the label's offset in the y direction.
    * @param offset int
    */
   public int getOffsetY() {
     return box.yoffset;
   }


   public void draw(DrawingPanel panel, Graphics g) {
      String tempText = text; // local reference for thread safety
      if(tempText==null) {
         return;
      }
      super.draw(panel, g);
      box.computeBoxMetrics(panel,g);
      int xpix = panel.xToPix(x);
      int ypix = panel.yToPix(y);
      g.setColor(Color.YELLOW);
      g.drawLine(xpix, ypix, box.connectX, box.connectY);
      g.setColor(Color.BLACK);
      box.draw(panel, g);
   }

  public Interactive findInteractive(DrawingPanel panel, int xpix, int ypix) {
    if(box.isInside( panel,  xpix, ypix)){
      return box;
    }else{
      return null;
    }
  }

  /**
   * Checks to see if this object is enabled and if the pixel coordinates are inside the drawable.
   *
   * @param panel
   * @param xpix
   * @param ypix
   * @return true if the pixel coordinates are inside; false otherwise
   */
  public boolean isInside(DrawingPanel panel, int xpix, int ypix) {
    return box.isInside(panel, xpix, ypix);
  }


  /**
   * Enables mouse interactions
   * @param enabled boolean
   */
  public void setEnabled(boolean enabled) {
    this.enabled=enabled;
    box.setEnabled(enabled);
  }

  /**
   * Gets the mouse interaction enabled property.
   * @return boolean
   */
  public boolean isEnabled() {
    return enabled;
  }

  class Box extends AbstractInteractive {

      int leftPix, topPix;
      int boxHeight = 0, boxWidth = 0; // the box width and height
      int xpix = 0, ypix = 0;
      int xoffset=0, yoffset=0;
      int connectX, connectY;
      DrawingPanel panel;

      /**
       * Draws the box and the text.
       *
       * @param panel DrawingPanel
       * @param g Graphics
       */
      public void draw(DrawingPanel panel, Graphics g) {
         this.panel=panel;
         String tempText = text; // local reference for thread safety
         if(tempText==null) {
            return;
         }
         Graphics2D g2 = (Graphics2D) g;
         g2.setColor(color);
         Font oldFont = g2.getFont();
         g2.setFont(font);
         Shape clipShape = g2.getClip();
         g2.setClip(0, 0, panel.getWidth(), panel.getHeight());
         g2.setColor(Color.YELLOW);
         g2.fillRect(leftPix, topPix, boxWidth, boxHeight);
         g2.setColor(Color.BLACK);
         g2.drawRect(leftPix, topPix, boxWidth, boxHeight);
         g2.drawString(tempText, leftPix+3, topPix+boxHeight-2);
         g2.setFont(oldFont);
         g2.setClip(clipShape);
      }

      void computeBoxMetrics(DrawingPanel panel,Graphics g){
        String tempText = text; // local reference for thread safety
        if(tempText==null || panel==null) {
           return;
        }
        Graphics2D g2 = (Graphics2D) g;
        Font oldFont = g2.getFont();
        g2.setFont(font);
        FontMetrics fm = g2.getFontMetrics();
        int sh = fm.getAscent()+2;           // current string height
        int sw = fm.stringWidth(tempText)+6; // current string width
        boxHeight = Math.max(boxHeight, sh);
        boxWidth = Math.max(boxWidth, sw);
        xpix = panel.xToPix(InteractiveLabel.this.x);
        ypix = panel.yToPix(InteractiveLabel.this.y);
        connectX = leftPix = xpix+xoffset;
        connectY = topPix = ypix+yoffset;
        if(InteractiveLabel.this.connection_location==TOP_CENTER_LOCATION) {
           connectX += boxWidth/2;
         }else if(InteractiveLabel.this.connection_location==CENTER_LOCATION) {
            connectX += boxWidth/2;
            connectY += boxHeight/2;
         }
        g2.setFont(oldFont);
      }

      public void setXY(double x, double y) {
        if(panel==null) return;
        int x1=panel.xToPix(InteractiveLabel.this.x);
        int x2=panel.xToPix(x);
        xoffset=x2-x1;
        int y1=panel.yToPix(InteractiveLabel.this.y);
        int y2=panel.yToPix(y);
        yoffset=y2-y1;
      }


      public boolean isInside(DrawingPanel panel, int xpix, int ypix) {
         if((xpix>=leftPix)&&(xpix<=leftPix+boxWidth)&&(ypix>=topPix)&&(ypix<=topPix+boxHeight)) {
            return true;
         }
         return false;
      }
   }
}
/*
 * Open Source Physics software is free software; you can redistribute
 * it and/or modify it under the terms of the GNU General Public License (GPL) as
 * published by the Free Software Foundation; either version 2 of the License,
 * or(at your option) any later version.
 *
 * Code that uses any portion of the code in the org.opensourcephysics package
 * or any subpackage (subdirectory) of this package must must also be be released
 * under the GNU GPL license.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston MA 02111-1307 USA
 * or view the license online at http://www.gnu.org/copyleft/gpl.html
 *
 * Copyright (c) 2007  The Open Source Physics project
 *                     http://www.opensourcephysics.org
 */
